import {guid, isEmpty, isNotEmpty, real} from '@/utils/CommonUtils';
import AuthHelper from '@/components/platwork/FormDetailComponent/DefaultFormDetailComponent/AuthHelper';
import {postAction} from '@/request/BaseRequest';
import {ElMessage} from 'element-plus';

export default class {
  formData;
  formDefinition;
  authHelper;
  viewAction;
  pageAction;
  subFormSelectionKeysMap = {};
  refsMap = {
    $refs: {},
    $nextTick: () => {
    },
  };

  constructor(formData, formDefinition, refsMap, viewAction, pageAction) {
    if (isEmpty(formData) || isEmpty(formDefinition)) return; //解决初始加载问题
    this.formData = real(formData);
    this.formDefinition = real(formDefinition);
    this.refsMap = real(refsMap);
    this.viewAction = real(viewAction);
    this.pageAction = real(pageAction);

    this.subFormSelectionKeysMap = {};
    this.fillFormDataByDefinition();
    this.authHelper = new AuthHelper(this.formDefinition, this.formData, this.viewAction);
  }

  init() {
    this.setFormDataToComponents();
    if (this.pageAction === 'static') return;
    return this.updatAllAuth();
  }

  fillFormDataByDefinition() {
    this.fillMainFieldData();
    this.fillSubFormData();
  }

  fillMainFieldData() {
    let formData = this.formData;
    let {formFields} = this.formDefinition;
    if (isEmpty(formFields)) formFields = [];
    for (let i = 0; i < formFields.length; i++) {
      let field = formFields[i];
      if (isEmpty(formData[field.tableFieldName])) {
        formData[field.tableFieldName] = undefined;
      }
    }
  }

  fillSubFormData() {
    let {subForms} = this.formDefinition;
    if (isEmpty(subForms)) {
      this.formDefinition.subForms = [];
      return;
    }

    subForms.forEach(subForm => {
      this.fillSubFormDataBySubForm(subForm);
    });
  }

  fillSubFormDataBySubForm(subForm) {
    let {fields} = subForm;
    subForm = subForm.subForm;
    let subFormDatas = this.formData.subFormDatas;
    if (isEmpty(subFormDatas)) {
      this.formData.subFormDatas = [];
      return;
    }
    this.doFillSubFormDataBySubForm(subForm, fields, subFormDatas);
  }

  doFillSubFormDataBySubForm(subForm, fields, subFormDatas) {
    let subFormId = subForm.id;
    let subFormData = subFormDatas.find(s => s.formId === subFormId);
    if (isEmpty(subFormData)) {
      subFormDatas.push({
        formId: subFormId,
        formDatas: [],
      });
      subFormData = subFormDatas.find(s => s.formId === subFormId);
    }
    let subFormDataItems = subFormData.formDatas;
    this.doFillSubFormDataBySubFormItem(fields, subFormDataItems);
  }

  doFillSubFormDataBySubFormItem(fields, subFormDataItems) {
    if (isEmpty(fields) || isEmpty(subFormDataItems)) return;
    subFormDataItems.forEach(item => {
      fields.forEach(field => {
        let fieldName = field.tableFieldName;
        if (isEmpty(item[fieldName])) {
          item[fieldName] = undefined;
        }
      });
    });
  }

  getFieldDefinition(component) {
    if (isEmpty(this.formData) || isEmpty(this.formDefinition)) return;
    let originFieldId = component.fieldId;
    let field = this.formDefinition.formFields.find(f => f.originId === originFieldId);
    if (!isEmpty(field)) return field;

    let {subForms} = this.formDefinition;
    if (isEmpty(subForms)) return component;
    for (let i = 0; i < subForms.length; i++) {
      let {fields} = subForms[i];
      for (let j = 0; j < fields.length; j++) {
        if (fields[j].originId === originFieldId) return fields[j];
      }
    }

    return component;
  }

  getFeildRefs(componentDefine) {
    if (isEmpty(this.formData) || isEmpty(this.formDefinition)) return;

    let {formFields} = this.formDefinition;
    let index = formFields.findIndex(f => f.originId === componentDefine.fieldId);
    if (index === -1) return guid();
    return this.createMainFeildRefs(formFields[index].tableFieldName);
  }

  createMainFeildRefs(tableFieldName) {
    return `${tableFieldName}Component`;
  }

  getDetailDataSource(component) {
    if (isEmpty(this.formDefinition)) return [];
    let subFormId = component.subFormId;
    let subForm = this.getSubFormByOriginSubFormId(subFormId);
    subFormId = subForm.id;
    let datas = this.formData.subFormDatas.find(data => data.formId === subFormId);

    if (!datas) {
      this.formData.subFormDatas.push(datas = {
        formId: subFormId,
        formDatas: []
      });
    }
    return datas.formDatas;
  }

  getSubFormByOriginSubFormId(originSubFormId) {
    let {subForms} = this.formDefinition;
    let subForm = subForms.find(s => s.subForm.originId === originSubFormId);
    if (isEmpty(subForm)) {
      throw new Error('渲染子表报错: 根据子表原始id: ' + originSubFormId + '没有找到子表');
    }

    return subForm.subForm;
  }

  getSubFormById(id) {
    let {subForms} = this.formDefinition;
    let subForm = subForms.find(s => s.subForm.id === id);
    if (isEmpty(subForm)) {
      throw new Error('渲染子表报错: 根据子表id: ' + id + '没有找到子表');
    }

    return subForm.subForm;
  }

  getSubFormFieldsById(id) {
    let {subForms} = this.formDefinition;
    let subForm = subForms.find(s => s.subForm.id === id);
    if (isEmpty(subForm)) {
      throw new Error('渲染子表报错: 根据子表id: ' + id + '没有找到子表');
    }

    return subForm.fields;
  }

  getSelectTableKeys(component) {
    if (isEmpty(this.formDefinition)) return [];
    let originSubFormId = component.subFormId;
    let subForm = this.getSubFormByOriginSubFormId(originSubFormId);
    let subFormId = subForm.id;
    if (!this.subFormSelectionKeysMap[subFormId]) {
      this.subFormSelectionKeysMap[subFormId] = [];
    }

    return this.subFormSelectionKeysMap[subFormId];
  }

  addSubTableRow(component) {
    this.doAddSubTableRow(component).then((rowData, subForm) => {
      this.setFormDataToComponents();
      // this.updatAllAuth();
      this.updateSubFormRowAuth(rowData, subForm);
    });
  }

  doAddSubTableRow(component) {
    let originSubFormId = component.subFormId;
    let subForm = this.getSubFormByOriginSubFormId(originSubFormId);
    let subFormId = subForm.id;

    let datas = this.getDetailDataSource(component);
    return new Promise((success, err) => {
      this.createSubFormRow(subForm).then(rowData => {
        rowData.isNewRow = true;
        datas.push(rowData);
        this.authHelper.addSubTableRow(subForm, rowData);
        this.$nextTick(() => {
          success(rowData, subForm);
        });
      });
    });
  }

  updateSubFormRowAuth(rowData, subForm) {
    this.$nextTick(() => {
      this.authHelper.updateSubFormRowAuth(rowData, subForm, this.getFormData());
    });
  }

  removeSubTableRow(component) {
    return new Promise((success, err) => {
      let keys = this.getSelectTableKeys(component);
      if (isEmpty(keys)) return;
      let datas = this.getDetailDataSource(component);
      let list = datas.filter(row => {
        let index = keys.findIndex(key => key === row.id);
        return index === -1;
      });
      datas.splice(0, datas.length);
      keys.splice(0, keys.length);
      datas.push(...list);

      this.getFormData();
      this.$nextTick(() => {
        this.setFormDataToComponents();
      });
      success();
    });
  }

  removeSingleSubTableRow(component, item) {
    let datas = this.getDetailDataSource(component);

    let list = datas.filter(row => row.id !== item.id);
    datas.splice(0, datas.length);
    datas.push(...list);

    this.getFormData();
    this.$nextTick(() => {
      this.setFormDataToComponents();
    });
  }

  setFormDataToComponents() {
    this.$nextTick(() => {
      this.setMainFormDataToComponents();
      this.setSubFormDataToComponents();
    });
  }

  updatAllAuth() {
    if (isEmpty(this.formDefinition) || isEmpty(this.viewAction) || isEmpty(this.formData))
      return;
    return new Promise((success, err) => {
      this.$nextTick(() => {
        this.doUpdatAllAuth().then(success);
      });
    });
  }

  doUpdatAllAuth() {
    let updatAllAuthContext = {
      viewActionId: this.viewAction.id,
      formBean: this.getFormData()
    };

    return this.authHelper.updatAllAuth(updatAllAuthContext);
  }

  setMainFormDataToComponents() {
    if (isEmpty(this.formDefinition)) return;
    let {formFields} = this.formDefinition;
    if (isEmpty(formFields)) return;

    formFields.forEach(field => {
      let {tableFieldName} = field;
      let refsName = this.createMainFeildRefs(tableFieldName);
      let ref = this.getRefComponent(refsName);
      if (isEmpty(ref)) return;
      ref.setFieldValue(this.formData[tableFieldName], this.formData);
    });
  }

  setSubFormDataToComponents() {
    if (isEmpty(this.formData)) return;
    let {subFormDatas} = this.formData;
    if (isEmpty(subFormDatas)) return;

    subFormDatas.forEach(subFormData => {
      let {formId, formDatas} = subFormData;
      let subForm = this.getSubFormById(formId);
      let subFormFields = this.getSubFormFieldsById(formId);

      formDatas.forEach(rowData => {
        subFormFields.forEach(subFormField => {
          let {tableFieldName} = subFormField;
          let refsName = this.createSubFieldRefs(subForm.formName, subFormField.tableFieldName, rowData.id);
          let refComponent = this.getRefComponent(refsName);
          if (isEmpty(refComponent)) return;

          refComponent.setFieldValue(rowData[tableFieldName], rowData);
        });
      });
    });
  }

  $nextTick(callback) {
    this.refsMap.$nextTick(callback);
  }

  clearSubTableRow(component) {
    return new Promise((success, err) => {
      let datas = this.getDetailDataSource(component);
      datas.splice(0, datas.length);
      success();
    });
  }

  getSubFiedldRefs(component, item) {
    let field = this.getFieldDefinition(component);
    let formId = field.formId;
    let subForm = this.getSubFormById(formId);
    return this.createSubFieldRefs(subForm.formName, field.tableFieldName, item.id);
  }

  createSubFieldRefs(formName, tableFieldName, id) {
    return `${formName}_${tableFieldName}_${id}`;
  }

  createSubFormRow(subForm) {
    let subFormData = {
      id: guid(),
      formId: subForm.id
    };

    let initSubDataVoContext = {
      subFormName: subForm.formName,
      viewActionId: this.viewAction.id,
      subFormData,
      formData: this.getFormData()
    };

    return new Promise((success, err) => {
      postAction('/plat/initSubData', initSubDataVoContext).then(data => {
        if (data.success) {
          let result = data.result;
          success(result);
        }
      });
    });
  }

  getFormData() {
    this.parseMainFields();
    this.parseSubFields();

    this.formData.tableName = this.formDefinition.form.tableName;
    this.formData.formId = this.formDefinition.form.id;
    this.formData.viewActionId = this.viewAction.id;
    return this.formData;
  }

  getFormDataWithCheck() {
    return new Promise((success, err) => {
      try {
        this.parseMainFieldsWithCheck();
        this.parseSubFieldsWithCheck();
        this.checkSunRowCount();
      } catch (e) {
        err(e)
        ElMessage.warning(e.message);
        return;
      }

      this.formData.tableName = this.formDefinition.form.tableName;
      this.formData.formId = this.formDefinition.form.id;
      this.formData.viewActionId = this.viewAction.id;
      success(this.formData);
    });
  }

  checkSunRowCount() {
    let {subForms} = this.formDefinition;
    subForms.forEach(subForm => {
      subForm = subForm.subForm;
      let {subFormButtonAction} = this.viewAction;
      let action = subFormButtonAction.find(action => action.subFormId === subForm.id);
      let {defaultMinLines} = action;

      if (isEmpty(defaultMinLines)) return;

      let formDatas = this.getSubFormDatasByFormId(subForm.id);
      let size = isEmpty(formDatas) ? 0 : formDatas.length;
      if (parseInt(size + '') < parseInt(defaultMinLines + '')) {
        throw new Error(`${subForm.showName}至少需要${defaultMinLines}条数据`);
      }
    });
  }

  getSubFormDatasByFormId(subFormId) {
    if (isEmpty(this.formDefinition) || isEmpty(this.formData)) return null;
    let {subFormDatas} = this.formData;

    let res = subFormDatas.find(s => s.formId === subFormId);
    if (isEmpty(res)) return [];
    return res.formDatas;
  }

  parseSubFields() {
    let {subFormDatas} = this.formData;
    if (isEmpty(subFormDatas)) return;
    subFormDatas.forEach(subFormData => {
      let {formId, formDatas} = subFormData;
      if (isEmpty(formId) || isEmpty(formDatas)) return;
      let subForm = this.getSubFormById(formId);
      let subFormFields = this.getSubFormFieldsById(formId);
      formDatas.forEach(rowData => {
        subFormFields.forEach(field => {
          let value = undefined, fieldName = field.tableFieldName;

          let refsName = this.createSubFieldRefs(subForm.formName, fieldName, rowData.id);
          let ref = this.getRefComponent(refsName);

          if (isEmpty(ref)) {
            //可能是页面没有渲染, 也可能是当前页面没有显示这个组件
          } else {
            value = ref.getFieldValue(rowData);
            rowData[fieldName] = value;
          }
          rowData.formName = subForm.formName;
          rowData.tableName = subForm.tableName;
        });
      });
    });
  }

  parseSubFieldsWithCheck() {
    let {subFormDatas} = this.formData;
    if (isEmpty(subFormDatas)) return;
    subFormDatas.forEach(subFormData => {
      let {formId, formDatas} = subFormData;
      if (isEmpty(formId) || isEmpty(formDatas)) return;
      let subForm = this.getSubFormById(formId);
      let subFormFields = this.getSubFormFieldsById(formId);
      formDatas.forEach(rowData => {
        subFormFields.forEach(field => {
          let value = undefined, fieldName = field.tableFieldName;

          let refsName = this.createSubFieldRefs(subForm.formName, fieldName, rowData.id);
          let ref = this.getRefComponent(refsName);

          if (isEmpty(ref)) {
            //可能是页面没有渲染, 也可能是当前页面没有显示这个组件
          } else {
            value = ref.getFieldValueWithCheck(rowData);
            rowData[fieldName] = value;
          }
          rowData.formName = subForm.formName;
          rowData.tableName = subForm.tableName;
        });
      });
    });
  }

  parseMainFields() {
    let {formFields} = this.formDefinition;
    formFields.forEach(field => {
      let refsName = this.createMainFeildRefs(field.tableFieldName);
      if (isEmpty(refsName)) return;
      let ref = this.getRefComponent(refsName);
      let value = undefined, fieldName = field.tableFieldName;
      if (isEmpty(ref)) {
        //可能是页面没有渲染, 也可能是当前页面没有显示这个组件
      } else {
        value = ref.getFieldValue(this.formData);
        this.formData[fieldName] = value;
      }
    });
  }

  parseMainFieldsWithCheck() {
    let {formFields} = this.formDefinition;
    formFields.forEach(field => {
      let refsName = this.createMainFeildRefs(field.tableFieldName);
      if (isEmpty(refsName)) return;
      let ref = this.getRefComponent(refsName);
      let value = undefined, fieldName = field.tableFieldName;
      if (isEmpty(ref)) {
        //可能是页面没有渲染, 也可能是当前页面没有显示这个组件
      } else {
        value = ref.getFieldValueWithCheck(this.formData);
        this.formData[fieldName] = value;
      }
    });
  }


  getRefComponent(refsName) {
    let res = this.refsMap.$refs[refsName];
    if (isEmpty(res)) return null;
    return res[0];
  }

  fieldValueChange(fieldDefinition, dataId) {
    let formData = this.getFormData();
    if (this.isMainField(fieldDefinition)) {
      this.authHelper.mainFieldValueChange(fieldDefinition, formData);
    } else {
      this.authHelper.subFieldValueChange(fieldDefinition, formData, dataId);
    }
  }

  isMainField(fieldDefinition) {
    if (isEmpty(fieldDefinition)) return;
    let {formFields} = this.formDefinition;
    let field = formFields.find(f => f.id === fieldDefinition.id);
    return !!field;
  }

  getMainFieldAuth(component) {
    if (this.pageAction === 'static') return 'static';
    if (isEmpty(this.authHelper) || isEmpty(this.formDefinition)) return;
    let field = this.getFieldDefinition(component);
    return this.authHelper.getMainFieldAuth(field);
  }

  getFieldRelations(component) {
    if (isEmpty(this.formDefinition)) return [];
    let fieldDefinition = real(this.getFieldDefinition(component));
    let fieldFormName = this.getFieldFormName(fieldDefinition);

    let formRelationVos = real(this.formDefinition).formRelationVos;
    if (isEmpty(formRelationVos)) return [];
    let res = [];

    for (let i = 0; i < formRelationVos.length; i++) {
      let formRelation = formRelationVos[i];
      let mainFieldRelation = this.getMainFormRelation(formRelation);
      if (mainFieldRelation.originField === fieldDefinition.tableFieldName
        && mainFieldRelation.originFormName === fieldFormName) {
        res.push(formRelation);
      }
    }
    return res;
  }

  getFieldFormName(fieldDefinition) {
    if (isNotEmpty(this.formDefinition.formFields.find(f => f.id === fieldDefinition.id))) {
      return this.formDefinition.form.formName;
    }
    let {subForms} = this.formDefinition;
    for (let i = 0; i < subForms.length; i++) {
      let {fields, subForm} = subForms[i];
      if (isNotEmpty(fields.find(f => f.id === fieldDefinition.id))) {
        return subForm.formName;
      }
    }
    return undefined
  }

  getMainFormRelation(formRelation) {
    let {fieldRelations} = formRelation;
    for (let i = 0; i < fieldRelations.length; i++) {
      if (fieldRelations[i].selector) {
        return fieldRelations[i];
      }
    }
    return undefined;
  }

  getMainFieldNotNull(component) {
    if (isEmpty(this.authHelper) || isEmpty(this.formDefinition)) return;
    let field = this.getFieldDefinition(component);
    return this.authHelper.getMainFieldNotNull(field);
  }

  getSubFieldAuth(component, rowData) {
    if (this.pageAction === 'static') return 'static';
    let field = this.getFieldDefinition(component);
    return this.authHelper.getSubFieldAuth(field, rowData);
  }

  getSubFieldNotNull(component, rowData) {
    let field = this.getFieldDefinition(component);
    return this.authHelper.getSubFieldNotNull(field, rowData);
  }

  hasAddAuth(component) {
    if (this.pageAction === 'static') return false;
    if (isEmpty(this.formDefinition) || isEmpty(this.viewAction)) return false;
    let subForm = this.getSubFormByOriginSubFormId(component.subFormId);
    if (isEmpty(subForm)) return false;
    let {subFormButtonAction} = this.viewAction;
    if (isEmpty(subFormButtonAction)) return false;
    let action = subFormButtonAction.find(action => action.subFormId === subForm.id);
    if (isEmpty(action)) return false;
    return action.defaultAddButtonAuth + '' === '1';
  }

  hasRemoveAuth(component) {
    if (this.pageAction === 'static') return false;
    if (isEmpty(this.formDefinition) || isEmpty(this.viewAction)) return false;
    let subForm = this.getSubFormByOriginSubFormId(component.subFormId);
    if (isEmpty(subForm)) return false;
    let {subFormButtonAction} = this.viewAction;
    if (isEmpty(subFormButtonAction)) return false;
    let action = subFormButtonAction.find(action => action.subFormId === subForm.id);
    if (isEmpty(action)) return false;
    return action.defaultRemoveButtonAuth + '' === '1';
  }

  isNewRow(item) {
    return !!item.isNewRow;
  }

  doRelation(relationParams) {
    let formData = this.getFormData();
    let data = {
      formData,
      ...relationParams
    }
    console.log(data);
    loading.value = true
    postAction('/plat/platRelation/doRelation', data).then(data => {
      loading.value = false
      if (data.success) {
        let result = data.result;
        console.log(result);
      }
    })
  }
};
